package org.webframe.oauth2;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

/**
 * 配置授权服务器
 * 
 * @author yin.jinbiao
 *
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
	
    /**
     * 注入authenticationManager
     * 来支持 password grant type
     */
    @Autowired
    private AuthenticationManager authenticationManager;

	@Autowired
	private DataSource dataSource;
	
	@Bean
	public TokenStore tokenStore(){
		return new JdbcTokenStore(dataSource);
	}
	
	@Bean
	public JdbcClientDetailsService jdbcClientDetailsService(){
		return new JdbcClientDetailsService(dataSource);
	}

	/**
	 * 配置ClientDetailsService
	 * 注意，除非你在下面的configure(AuthorizationServerEndpointsConfigurer)
	 * 中指定了一个AuthenticationManager，否则密码授权方式不可用。 至少配置一个client，否则服务器将不会启动。
	 */
	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		// 配置客户端-基于内存模式
        //clients.inMemory().withClient("client").secret(passwordEncoder.encode("secret")).authorizedGrantTypes("authorization_code").scopes("app").redirectUris("http://www.funtl.com");
        //jdbc模式
		clients.withClientDetails(jdbcClientDetailsService());
		
	}

	/**
	 * 该方法是用来配置Authorization Server
	 * endpoints的一些非安全特性的，比如token存储、token自定义、授权类型等等的
	 * 默认情况下，你不需要做任何事情，除非你需要密码授权，那么在这种情况下你需要提供一个AuthenticationManager
	 */
	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager);//token存储
	}
	
	/**
	 * 配置授权服务器的安全，意味着实际上是/oauth/token端点。 /oauth/authorize端点也应该是安全的
	 * 默认的设置覆盖到了绝大多数需求，所以一般情况下你不需要做任何事情。
	 */
	@Override
	public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
		security
        // 开启/oauth/token_key验证端口无权限访问
        .tokenKeyAccess("permitAll()")
        // 开启/oauth/check_token验证端口认证权限访问
        .checkTokenAccess("isAuthenticated()")
        .allowFormAuthenticationForClients();

	}


}
